/* Copyright (c) 2001 Nextel Communications, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *   - Neither the name of Nextel Communications, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived from
 *     this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NEXTEL
 * COMMUNICATIONS, INC. OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package com.nextel.ui.custom;

import com.nextel.ui.*;
import com.nextel.util.Debug;
import com.nextel.util.Logger;
import com.nextel.util.lwuit.Font;
import java.util.Vector;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import pe.com.nextel.util.List;

/**
 * A list of items which may not all be displayed at once and whose display is
 * scrollable if not all items are displayed.
 * <p><b>Example:</b><img src="doc-files/ScrollList.jpg">
 * <p>
 * If not all items are displayed then a vertical scroll bar is displayed to the
 * right of the list; if all items are displayed (i.e., all items fit within
 * the height available for the display) then no scroll bar is displayed.
 * <p>
 * The currently selected item is reverse-videoed while unselected items have
 * normal video.  The currently selected item may optionally be in a different
 * font than the unselected items.
 *
 * @author Glen Cordrey
 * @autor Edgard Espinoza
 */
public class OScrollListWrap extends OFocusableComponent {
    
    private boolean modeWrap;
    private String label;
    private Font labelFont;
    private int labelWidth;
    public OListenerKey listenerKey;
    public boolean isWithBorder = true;
//    public boolean flagPaint = true;
    // The height of text for the selected item.
    private int selectedTextHeight;
    // The height of text for items which are not selected.
    private int unselectedTextHeight;
    // The font to use for the selected item
    private Font selectedFont;
    // The font to use for unselected items
    private Font unselectedFont;
    // width of the scroll list, including the scrollbar width
    private int width;
    // width of the list in pixels, excluding the scrollbar width
    private int listWidth;
    // the height of the list in pixels
    private int height;
    // the number of lines which can be displayed in the available space
    private int nbrOfDisplayableLines;
    // the number of lines which are displayed in the available space; equal to or
    // less than nbrOfDisplayableLines
    private int nbrOfDisplayedLines;
    // the index in the list of the first line displayed
    private int topLineIndex;
    // the index in the list of the last line displayed
    private int bottomLineIndex;
    // 0-based index of the selected displayed row.  this index is NOT an index
    // into the list of items, but is the index of the row in the scroll list
    // display.  e.g., if 3 items can be displayed in the scroll list window, this
    // will have a value of 0, 1, or 2
    private int lineSelected;
    // the set of items which may be displayed
    private List items;
    private Image[] images;
    private OScrollBar scrollBar;
    private boolean firstTime = true;
    private int maxHeight = 0;
    // renderer used to render the list items
    private ORenderer itemORenderer;
    // default renderer, which simply displays the item as a String.  This can
    static private ORenderer defaultORenderer =
            new ORenderer() {
        
        public void render(com.nextel.util.lwuit.Graphics g, int x, int y, int width,
                String item, Image image) {
//	  String value = ( item instanceof String
//			   ? ( String ) item
//			   : item.toString() );
            //if(y < image.getHeight()) y = image.getHeight();
//            System.out.println("---------sodomia");
            if (image != null) {
                g.drawImage(image, x, y);
            }
            
            g.drawString(item, image != null ? x + image.getWidth() + 5 : x, y);
        } // render
    } /* defaultORenderer */;
    
    /**
     * Creates a new <code>OScrollList</code> instance.
     *
     * @param width The width of the scroll list.  If any items in the list are
     * wider than this their display will be truncated.
     * @param maxHeight The height available for the scroll list.  The
     * actual height of the list may be less than this, and is derived from the
     * number of lines which can be displayed in the maxHeight.
     * @param selectedFont Font to use for the selected item
     * @param unselectedFont Font to use for the unselected items
     */
    public  OScrollListWrap(int width,
            int pmaxHeight,
            Font selectedFont,
            Font unselectedFont) {
        super();
//        if ( Debug.ON ) Logger.dev( "OScrollList.ctor.3 ENTERED" );
        
        // default traverseDirections for OFocusableComponent include UP and DOWN, so
        // limit to right and left only
        setTraverseDirections(OFocusableComponent.RIGHT | OFocusableComponent.LEFT);
        setFocusedComponentBackground(OColor.TRANSPARENT);
        
        this.selectedTextHeight = selectedFont.getHeight();
        this.unselectedTextHeight = unselectedFont.getHeight();
        this.selectedFont = selectedFont;
        this.unselectedFont = unselectedFont;
        this.width = width;
        this.listWidth = width;
        this.maxHeight = pmaxHeight;
        
        calulateList(this.selectedTextHeight, this.unselectedTextHeight, pmaxHeight);
        
//        if ( Debug.ON ) Logger.dev( "OScrollList.init EXITTING" );
        
    } // OScrollList
    
    public void setImages(Image[] imag,int maxHeight) {
        this.images = imag;
        
        
        if (this.unselectedTextHeight < this.images[0].getHeight()) {
            this.unselectedTextHeight = this.images[0].getHeight();
        }
        
        calulateList(this.selectedTextHeight, this.unselectedTextHeight, maxHeight);
        
        this.height = (OUILook.STRING_SPACER_HEIGHT - 1) + selectedTextHeight +
                (unselectedTextHeight * (nbrOfDisplayedLines - 1)) + 5;
        //System.out.println(" this.height " + this.height);
        
    }
    
    private synchronized void calulateList(int altoSel, int altoNoSel, int maxHeight) {
        
        
        this.selectedTextHeight = altoSel;
        this.unselectedTextHeight = altoNoSel;
        
        
        int heightAvailableForNotSelectedText = maxHeight -
                OUILook.STRING_SPACER_HEIGHT - selectedTextHeight;
        
        this.nbrOfDisplayableLines = 1 /* selected line */ +
                (heightAvailableForNotSelectedText / unselectedTextHeight);
        
        
        this.bottomLineIndex = numeroLineasMostradas - 1;
        
        //this.height = maxHeight;
    }
    
    /**
     * Populates the list with the items to display.
     * You might want to use this version of populate, rather than
     * {@link #populate( String [] ) populate( String[] )}, if you need to align
     * columns within your list, or if you want to display in the list things
     * other than strings, both of which you could do by supplying a custom
     * renderer.
     *
     * @param items The items to display.
     * @param renderer A renderer to use for rendering the items to the screen.
     */
    public void populate(List items, ORenderer renderer) {
        
        this.itemORenderer = renderer;
        
        layOut(items);
        
        return;
    } // populate
    
    /**
     * Populates the list with a set of items.
     *
     * @param items The items to be displayed in the list.  The items will be
     * rendered by a default string renderer.
     */
    public void populate(List items) {
        
        populate(items, defaultORenderer);
        
    } // populate
    
    /**
     * Lays out the list display.
     *
     * @param items The items to be displayed.
     */
    protected void layOut(List items) {
        this.items = items;
        
        recalcular();
    } // layOut
    
    /**
     * Gets the height of the scroll list.
     * @return Height of the scroll list. The height will be 0 until
     * {@link #populate populate} is called.
     */
    public int getHeight() {
//        if (Debug.ON) {
//            Logger.dev("OScrollList.getHeight CALLED, returning " +
//                    this.height);
//        }
        return this.height;
    }
    
    /**
     * Gets the width of the scroll list, including the scroll bar.
     * @return Width of the scroll list.
     */
    public int getWidth() {
//        if (Debug.ON) {
//            Logger.dev("OScrollList.getWidth CALLED, returning " +
//                    this.width);
//        }
        return this.width;
    }
    
    int numitems = 0;
    int numeroLineasMostradas = 0;
    int bajarY = 0;
    int  numerosWrapsEnlaPrimeraPasada = 0;
    
    private synchronized void calcularMedidas() {
        if (items != null) {
            
            nbrOfDisplayedLines = Math.min(items.size(), nbrOfDisplayableLines);
            
            numeroLineasMostradas = 0;
            numitems = 0;
            this.height = (OUILook.STRING_SPACER_HEIGHT - 1) + nbrOfDisplayableLines*unselectedFont.getHeight() + 5;
            
            Vector tmp = new Vector();
            
            //  long timpo1 = System.currentTimeMillis();
            numerosWrapsEnlaPrimeraPasada = 0;
            for (int listIndex = topLineIndex; items != null && listIndex >= 0 &&
                    listIndex < items.size(); listIndex++) {
                
                Font itemFont = unselectedFont;
                
                //long timpo2 = System.currentTimeMillis();
                
                WordWrap ww = new WordWrap(itemFont, (String) items.get(listIndex), getListWidth() - OUILook.H_GAP);
                ww.dividirPalabraSinSalto();
                
                numerosWrapsEnlaPrimeraPasada = numerosWrapsEnlaPrimeraPasada+ww.listaTexto.size()-1;
               // System.out.println("agregando numerosWrapsEnlaPrimeraPasada==" + numerosWrapsEnlaPrimeraPasada);
                numitems = numitems + 1;
                numeroLineasMostradas = numeroLineasMostradas +  ww.listaTexto.size();
                tmp.addElement(new Integer(ww.listaTexto.size()));
                
                ww.clear();
                ww = null;
                
                if (listIndex == (topLineIndex + lineSelected)) { // this is the selected line; reverse-video the background
                    itemFont = selectedFont;
                    if (nbrOfDisplayableLines <= numeroLineasMostradas){
                        bajarY = numeroLineasMostradas - nbrOfDisplayableLines;
                        break;
                    }else{
                        bajarY = 0;
                    }
                }
                
                if (nbrOfDisplayableLines <= numeroLineasMostradas){
                    break;
                }
            }
            
            if (bajarY >0){    //nuevo
                int lineasCambiar = bajarY;
                for(int i=0; i<tmp.size(); i++){
                    int intNumLin = ((Integer)tmp.elementAt(i)).intValue();
                    if (intNumLin<=lineasCambiar&&(lineasCambiar>0)){
                        lineasCambiar = lineasCambiar - intNumLin;
                        topLineIndex++;
                        numitems--;
                    }else{
                        break;
                    }
                }
                bajarY = lineasCambiar;
                
            }
            
            tmp.removeAllElements();
            tmp=null;
            
            this.bottomLineIndex = numitems - 1;
            
            if (bottomLineIndex >= items.size()) { // bottomLineIndex is leftover from previous deletion of the last row, so
                // correct it
                bottomLineIndex = items.size() - 1;
                topLineIndex = bottomLineIndex - numitems + 1;
            } else {
                bottomLineIndex = topLineIndex + numitems -1;//- 1;
            }
            
            
            if (lineSelected > numitems - 1) { // the number of items displayed has decreased
                lineSelected = numitems - 1;
            } 
        } 
    }
    
    /**
     * Paints the scroll list on the screen.
     *
     * @param g The graphics context
     */
    public synchronized void paint(Graphics g) {
        
        if(!needsRepaint()) return;
        
//        System.out.println("paint.needsRepaint()=" + needsRepaint( )+ "|items.size()=" +items  + "|nbrOfDisplayableLines=" + nbrOfDisplayableLines);
        
        this.listWidth = this.width;
        boolean mostrarBarra=false;
        
        
        if (items != null  ) {
          // System.out.println("items.size() + numerosWrapsEnlaPrimeraPasada" + items.size() +"|"+numerosWrapsEnlaPrimeraPasada);
          // System.out.println("nbrOfDisplayableLines="+ nbrOfDisplayableLines);
            if( nbrOfDisplayableLines  < items.size() + numerosWrapsEnlaPrimeraPasada ){
                mostrarBarra = true;
            }
            
            if(mostrarBarra){
                if (firstTime) { // create scrollbar
                    firstTime = false;
                    this.scrollBar = new OScrollBar();
                }
                this.listWidth -= scrollBar.getWidth()  ;
            }
        }
        numerosWrapsEnlaPrimeraPasada = 0;
        
//        if(items != null)
//            System.out.println("|items.size()=" +items.size());
        
        int oldColor = g.getColor(); // save so we can restore it
        
        int x = getX();
        int y = getY();
        
        com.nextel.util.lwuit.Graphics grap = new com.nextel.util.lwuit.Graphics(g);
        
        if (label != null) { // draw the label on the left, if their is one
            grap.setFont(labelFont);
            grap.drawString(label, x, y);
            
        }
        
        int boxLeftEdge = x + labelWidth;
        int boxTopEdge = y;
        
        this.height = (OUILook.STRING_SPACER_HEIGHT - 1) + numeroLineasMostradas*unselectedFont.getHeight() + 5;
        
        paintBoxList(isWithBorder, g, boxLeftEdge, y, listWidth+1, this.height);
        
        
        // adjust y to top of where string is to be
        y += OUILook.STRING_SPACER_HEIGHT;
        
        // display list items in the box
        grap.setColor(OUILook.TEXT_COLOR);
         
        calcularMedidas();
        
         int itemsAdicion = 0;
         
        if(topLineIndex < 0) topLineIndex = 0;
        
        for (int listIndex = topLineIndex; items != null && listIndex < items.size(); 
        listIndex++) {
            
            Font itemFont = unselectedFont;
            
            WordWrap ww = new WordWrap(itemFont, (String) items.get(listIndex), getListWidth() - OUILook.H_GAP);
            ww.dividirPalabraSinSalto();
            
            int foreground = OUILook.TEXT_COLOR;
            
            itemsAdicion = itemsAdicion + ww.listaTexto.size( ) - 1;
            
            if (listIndex == (topLineIndex + lineSelected)) { // this is the selected line; reverse-video the background
                grap.setColor(hasFocus() ? OColor.LISTA_ITEM_SELECTED : OColor.DK_GRAY);
                grap.fillRect(getX(), y - 1, listWidth, selectedTextHeight * ww.listaTexto.size( ));
                
                foreground = OColor.TRANSPARENT;
                itemFont = selectedFont;
            }
            
            
            grap.setFont(itemFont);
            
            grap.setColor(foreground);
            
            if (items != null) {
                
                int vez = 0;
                
                for (int indexValorWrap=0;   indexValorWrap < ww.listaTexto.size();indexValorWrap++) {
                    
                    String lineText = (String)ww.listaTexto.get(indexValorWrap);
                    
                    if (bajarY-- <= 0){
                        if (images != null) {
                            //                            
                            if (vez == 0){
                                itemORenderer.render(grap, x + OUILook.H_GAP, y,
                                        getListWidth() - OUILook.H_GAP, lineText, images[listIndex]);
                                vez = 1;
                            }else{
                                itemORenderer.render(grap, x + OUILook.H_GAP, y,
                                        getListWidth() - OUILook.H_GAP, lineText, null);
                            }
                            
                        } else {
                            
                            itemORenderer.render(grap, x + OUILook.H_GAP, y,
                                    getListWidth() - OUILook.H_GAP, lineText, null);
                            
                        }
                        
                        if (images != null && itemFont.getHeight() < images[listIndex].getHeight()) {
                            y += images[listIndex].getHeight() + 1;
                        } else {
                            y += itemFont.getHeight();
                        }
                    }
                    
                    if (y > this.height) {
                        break;
                    }
                }
                
                ww.clear();
                ww = null;
            }
            
            if (y > this.height) {
                break;
            }
        }
        
        if (scrollBar != null && items != null) {
            
//            if(itemsAdicion > 0 )
//                itemsAdicion = itemsAdicion ;
//            
            
            int percentageDisplayed = ( nbrOfDisplayedLines * 100 ) / (items.size( ) + itemsAdicion-1);
            
//            System.out.println("maxHeight =" + maxHeight);
//            System.out.println("this.height=" + this.height);
//            System.out.println("nbrOfDisplayedLines=" + nbrOfDisplayedLines );
//            System.out.println("percentageDisplayed="+ percentageDisplayed );
            
            int sliderStart = (topLineIndex * 100) / (items.size( ) + itemsAdicion-1);
            
            scrollBar.ancho( this.width - 4);
            scrollBar.paint(grap, boxLeftEdge + listWidth + 1, boxTopEdge,
                    /*this.height*/ maxHeight, sliderStart, percentageDisplayed);
        }
        
        g.setColor(oldColor);
        
    } // paint
    
    /**
     * Gets the list item that was selected
     *
     * @return The selected list item.
     */
    public Object getSelectedValue() {
        Object value = items.get(topLineIndex + lineSelected);
//        if (Debug.ON) {
//            Logger.dev("OScrollList.getSelectedValue CALLED, returning " + value);
//        }
        return value;
    } // getSelectedValue
    
    /**
     * Sets the item that is selected. If necessary the list will be scrolled so
     * that the item is displayed.
     *
     * @param value The item that is selected
     * @exception NotFoundException if the selected item does not exist
     */
    public void setSelectedValue(Object value)
    throws Exception {
//        if (Debug.ON) {
//            Logger.dev("OScrollList.setSelectedValue ENTERED w/value=" +
//                    value);
//        }
        boolean found = false;
        for (int idx = 0; idx < items.size(); idx++) {
            if (((String) items.get(idx)).equals(value)) {
                setSelectedIndex(idx);
                found = true;
                break;
            }
        }
        if (!found) {
            throw new Exception("OScrollList.setSelectedValue value " +
                    value + " not found");
        }
        repaint();
        if (Debug.ON) {
            Logger.dev("OScrollList.setSelectedValue EXITTING");
        }
    } // setSelectedValue
    
    /**
     * Sets the item that is selected. If necessary the list will be scrolled so
     * that the item is displayed.
     *
     * @param itemIndex The index, in the list of items, of the selected item.
     * @exception NotFoundException if no item with the specified index exists
     */
    public void setSelectedIndex(int itemIndex)
    throws Exception {
        if (Debug.ON) {
            Logger.dev("OScrollList.setSelectedValue ENTERED " +
                    " w/itemIndex= " + itemIndex);
        }
        if (itemIndex < topLineIndex || itemIndex > bottomLineIndex) {
            lineSelected = scrollTo(itemIndex);
        }
//        else {
//            System.out.println("---> 2");
//
//        }
        repaint();
        if (Debug.ON) {
            Logger.dev("OScrollList.setSelectedValue EXITTING");
        }
    } // setSelectedIndex
    
    /**
     * Scroll the list to display an item.
     *
     * @param itemIndex Index of the item to scroll to
     * @return The index, within the displayed rows, of the row scrolled to.
     * e.g., if the row scrolled to is the second of 3 displayed rows, the 0-based
     * index of 1 will be returned
     * @exception NotFoundException if no item with the specified index exists
     */
    public int scrollTo(int itemIndex)
    
    throws Exception {
        if (Debug.ON) {
            Logger.dev("OScrollList.scrollTo ENTERED w/itemIndex=" +
                    itemIndex);
        }
        if (itemIndex > items.size() - 1) {
            throw new Exception("requested index " + itemIndex +
                    " but there are only " + items.size() + " items");
        }
//        System.out.println("en el scrollTo...");
        if (itemIndex < topLineIndex || itemIndex > bottomLineIndex) {
            int lastIndex = items.size() - 1;
            if ((lastIndex - itemIndex + 1) >= numitems) { // place the item at the top of the scroll display
                topLineIndex = itemIndex + 1;
            } else // not enough items including and below the desired item to place it
            { // at the top, so place item at bottom of scroll display
                topLineIndex = itemIndex - numitems;
            }
            bottomLineIndex = topLineIndex + numitems - 1;
            repaint();
        }
        if (Debug.ON) {
            Logger.dev("OScrollList.scrollTo EXITTING, returning " +
                    (itemIndex - topLineIndex));
        }
        return itemIndex - topLineIndex;
    } // scrollTo
    
    /**
     * Gets the index of the item that is currently selected.
     *
     * @return the index of the currently selected item
     */
    public int getSelectedIndex() {
        if (Debug.ON) {
            Logger.dev("OScrollList.getSelectedIndex CALLED, returning " +
                    topLineIndex + lineSelected);
        }
        
        return topLineIndex + lineSelected;
    } // getSelectedIndex
    
    /**
     * Processes a key press while the scroll list has focus.
     * <p>
     * If the key pressed is the up- or down- key the list will be scrolled
     * appropriately and the selected item will change.  If the currently selected
     * item is the first or last item then a beep will ensue.  Any key other than
     * the up- or down- key is ignored.
     * @param keyCode The code of the pressed key.
     */
    public void keyPressed(int keyCode) {
//        if (Debug.ON) {
//        System.out.println("OScrollList.keyPressed w/keyCode= " + keyCode);
//        }
        
        int currentSelectionIndex = topLineIndex + lineSelected ;
        
        
        if (items!=null && items.size() > 0){
            
            if (keyCode == OAbstractScreen.DOWN_KEY) {
//                System.out.println("Down");
                if (items != null && currentSelectionIndex < items.size() -1) { // there is a row below the current selection
                    if (lineSelected < (numitems - 1)) {
                        lineSelected++;
                    }
//                    System.out.println("bottomLineIndexUP= " + bottomLineIndex);
                    if (++currentSelectionIndex > bottomLineIndex) { // scroll down
                        bottomLineIndex++;
                        topLineIndex++;
                    }
//                    flagPaint = true;
                    
                    repaint();
                    setNeedsRepaint(false);
                }
            } else if (keyCode == OAbstractScreen.UP_KEY) {
//                System.out.println("UP");
                if (items != null && currentSelectionIndex > 0) { // there is a row above the current selection
                    if (lineSelected > 0) {
                        lineSelected--;
                    }
//                    System.out.println("topLineIndexDown= " + topLineIndex);
                    if (--currentSelectionIndex < topLineIndex) { // scroll up
                        topLineIndex--;
                        bottomLineIndex--;
                    }
                    
                    repaint();
                    setNeedsRepaint(false);
                }
            } else {
//                System.out.println("entra aqui <> Down Up");
                if (listenerKey != null) {
                    listenerKey.performKey(getKeyIden(keyCode));
                }
            }
        }//aqui
    } // keyPressed
    
    
    private int getKeyIden(int keyCode) {
        keyCode = OBoxtField.changeChar(keyCode);
        switch (keyCode) {
            case 48:
                return 0;
            case 49:
                return 1;
            case 50:
                return 2;
            case 51:
                return 3;
            case 52:
                return 4;
            case 53:
                return 5;
            case 54:
                return 6;
            case 55:
                return 7;
            case 56:
                return 8;
            case 57:
                return 9;
            default:
                return keyCode;
        }
    }
    
    /**
     * Gets the width of the list portion of the scroll list, which excludes the
     * width of the scroll bar if one is displayed.
     *
     * @return The width of the list portion.
     */
    public int getListWidth() {
        return listWidth;
    } // getListWidth
    
    public boolean isModeWrap() {
        return modeWrap;
    }
    
    public void setModeWrap(boolean modeWrap) {
        this.modeWrap = modeWrap;
    }
    
//    public void setFlagPaint(boolean flag){
//        this.flagPaint=flag;
//    }
    
    public synchronized void recalcular() {
//        System.out.println("se entra a recalcular...");
        // System.out.println("items=" + items);
        
        if (items == null) {
            return;
        }
        nbrOfDisplayedLines = Math.min(items.size(), nbrOfDisplayableLines);
        if (bottomLineIndex >= items.size()) { // bottomLineIndex is leftover from previous deletion of the last row, so
            // correct it
            bottomLineIndex = items.size() - 1;
            
            topLineIndex = bottomLineIndex - numitems + 1;
            
            //  System.out.println("topLineIndex|bottomLineIndex|numitems==" + topLineIndex +"|"+ bottomLineIndex +"|"+ numitems);
            
        } else {
            bottomLineIndex = topLineIndex + numitems - 1;
        }
        
        this.height = (OUILook.STRING_SPACER_HEIGHT - 1) + numeroLineasMostradas*unselectedFont.getHeight() + 5;
        
        calcularMedidas();
        if (lineSelected > numitems - 1) { // the number of items displayed has decreased
            lineSelected = numitems - 1;
        }
    }
}// OScrollList

